package update_optimize_account

import (
	"adam2/internal/model"
	"anubis-framework/pkg/io"
	"anubis-framework/pkg/util"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"math/big"
)

// 买入之后更新optimize_account
type UpdateOptimizeAccountAfterBuy struct {
	db *gorm.DB
}

// 初始化
func (u *UpdateOptimizeAccountAfterBuy) Init(db *gorm.DB) {
	u.db = db
}

// 在买入之后更新optimize_account
func (u *UpdateOptimizeAccountAfterBuy) Exec(transactionDate string) {
	io.Infoln("在买入之后更新optimize_account")

	// 返回优化账户
	var optimizeAccountArray model.OptimizeAccountArray
	u.db.Table("optimize_account").Select("*").Order("id_ asc").Find(&optimizeAccountArray)

	for _, optimizeAccount := range optimizeAccountArray {

		// 股票资产
		var stockAssets float64 = 0
		// 当天买入的股票资产
		var currentBuyOrSellStockAssets float64 = 0
		// 买入股票的数量
		var sellOrBuyStockNumber int = 0

		// 计算每一个量化账户，在某一天买完股票后的收益
		var optimizeStockTransactRecordArray model.OptimizeStockTransactRecordArray
		u.db.Raw("select * from optimize_stock_transact_record qstr "+
			"where qstr.account_name = ? "+
			"and qstr.sell_date is null and qstr.sell_price is null and qstr.sell_amount is null",
			(*optimizeAccount).AccountName).Scan(&optimizeStockTransactRecordArray)

		// 如果没有买股票，则跳过
		if optimizeStockTransactRecordArray == nil || len(optimizeStockTransactRecordArray) == 0 {
			continue
		}

		for _, optimizeStockTransactRecord := range optimizeStockTransactRecordArray {
			// 查找某只股票在某一天的收盘价
			// 股票的收盘价
			var currentClosePrice float64 = -1
			u.db.Raw("select t.close_price from stock_transaction_data_all t "+
				"where t.code_ = ? and t.date_ = to_date(?, 'yyyy-mm-dd')",
				optimizeStockTransactRecord.StockCode, transactionDate).Scan(&currentClosePrice)

			if currentClosePrice == -1 {
				// 说明股票在这一天没有交易记录
				io.Infoln("股票[%s]在日期[%s]没有交易记录，可能是停牌，开始查找前一个交易日的记录", optimizeStockTransactRecord.StockCode, transactionDate)

				// 如果在某一天没有收盘价，比如停牌，则查找最近一个交易日的收盘价
				u.db.Raw("select std.close_price from (select * from stock_transaction_data_all t "+
					"where t.code_ = ? and t.date_ < to_date(?, 'yyyy-mm-dd') order by t.date_ desc) std where rownum <= 1",
					optimizeStockTransactRecord.StockCode, transactionDate).Scan(&currentClosePrice)
			}

			// 买入股票后的收益
			decimalValue := decimal.NewFromFloat(currentClosePrice)
			decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(optimizeStockTransactRecord.BuyAmount)))
			res, _ := decimalValue.Float64()
			a := new(big.Rat).SetFloat64(stockAssets)
			b := new(big.Rat).SetFloat64(res)
			stockAssets, _ = new(big.Rat).Add(a, b).Float64()
			sellOrBuyStockNumber = sellOrBuyStockNumber + 1

			// 计算当天买入的股票资产
			if util.DateToString(optimizeStockTransactRecord.BuyDate) == transactionDate {
				decimalValue := decimal.NewFromFloat(currentClosePrice)
				decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(optimizeStockTransactRecord.BuyAmount)))
				res, _ := decimalValue.Float64()
				a := new(big.Rat).SetFloat64(currentBuyOrSellStockAssets)
				b := new(big.Rat).SetFloat64(res)
				currentBuyOrSellStockAssets, _ = new(big.Rat).Add(a, b).Float64()
			}
		}

		// 更新optimize_account表
		var registrationFeeWhenBuy float64
		u.db.Raw("select COALESCE(sum(t1.registration_fee_when_buy), 0) from optimize_stock_transact_record t1 "+
			"where t1.account_name = ? and t1.sell_price is null and t1.sell_amount is null and t1.sell_date is null "+
			"and t1.buy_date=to_date(?,'yyyy-mm-dd')",
			(*optimizeAccount).AccountName, transactionDate).Scan(&registrationFeeWhenBuy)
		var commissionWhenBuy float64
		u.db.Raw("select COALESCE(sum(t1.commission_when_buy), 0) from optimize_stock_transact_record t1 "+
			"where t1.account_name = ? and t1.sell_price is null and t1.sell_amount is null and t1.sell_date is null "+
			"and t1.buy_date=to_date(?,'yyyy-mm-dd')",
			(*optimizeAccount).AccountName, transactionDate).Scan(&commissionWhenBuy)
		var totalStampDuty float64
		u.db.Raw("select COALESCE(sum(t1.stamp_duty), 0) from optimize_stock_transact_record t1 where t1.account_name = ?",
			(*optimizeAccount).AccountName).Scan(&totalStampDuty)
		var totalRegistrationFeeWhenBuy float64
		u.db.Raw("select COALESCE(sum(t1.registration_fee_when_buy), 0) from optimize_stock_transact_record t1 where t1.account_name = ?",
			(*optimizeAccount).AccountName).Scan(&totalRegistrationFeeWhenBuy)
		var totalCommissionWhenBuy float64
		u.db.Raw("select COALESCE(sum(t1.commission_when_buy), 0) from optimize_stock_transact_record t1 where t1.account_name = ?",
			(*optimizeAccount).AccountName).Scan(&totalCommissionWhenBuy)
		u.db.Exec("update optimize_account t "+
			"set t.hold_stock_number = ?, t.stock_assets = round(?, 4), "+
			"t.total_assets = round(? + t.capital_assets - ? - ? - ?, 4), "+
			// 下面这行可能有错，正确的可能是：资金资产=总资产-股票资产，否则资金资产部分可能就会出现负数。
			//"t.capital_assets = round(t.total_assets - ? - ? - ?, 4), "+
			"t.capital_assets = round(t.capital_assets - ? - ? - ?, 4), "+
			"t.total_registrate_fee_when_buy = ?,"+
			"t.total_commission_when_buy = ? "+
			"where t.account_name = ?",
			sellOrBuyStockNumber, stockAssets,
			stockAssets, currentBuyOrSellStockAssets, registrationFeeWhenBuy, commissionWhenBuy,
			currentBuyOrSellStockAssets, registrationFeeWhenBuy, commissionWhenBuy,
			totalRegistrationFeeWhenBuy,
			totalCommissionWhenBuy,
			(*optimizeAccount).AccountName)
	}
}
